<?php

namespace addons\mindmap\controller;

use app\common\controller\Api as Controller;
use fast\Random;
use think\Config;
use think\Cookie;
use think\Hook;
use think\Validate;

class Api extends Controller
{
    protected $noNeedLogin = ['login', 'init', 'register', 'logout', 'resetpwd'];
    protected $noNeedRight = ['*'];

    public function _initialize()
    {
        parent::_initialize();
        $auth = $this->auth;

        //监听注册登录注销的事件
        Hook::add('user_login_successed', function ($user) use ($auth) {
            $expire = input('post.keeplogin') ? 30 * 86400 : 0;
            Cookie::set('uid', $user->id, $expire);
            Cookie::set('token', $auth->getToken(), $expire);
        });
        Hook::add('user_register_successed', function ($user) use ($auth) {
            Cookie::set('uid', $user->id);
            Cookie::set('token', $auth->getToken());
        });
        Hook::add('user_delete_successed', function ($user) use ($auth) {
            Cookie::delete('uid');
            Cookie::delete('token');
        });
        Hook::add('user_logout_successed', function ($user) use ($auth) {
            Cookie::delete('uid');
            Cookie::delete('token');
        });
    }

    /**
     * 查询会员级别和网站logo
     */
    public function init()
    {
        $config = get_addon_config('mindmap');

        $thirdInfo = get_addon_info('third');
        $third     = get_addon_config('third');

        if (count($third) && $thirdInfo['state']) {
            $config['third'] = explode(',', $third['status']);
        } else {
            $config['third'] = [];
        }

        $config['logo'] = cdnurl($config['logo'], true);

        $this->success('查询成功', $config);
    }
    /**
     * 用户文件使用情况
     */
    public function userfileinfo()
    {
        $config = get_addon_config('mindmap');

        if (empty($config['user_group'][$this->auth->group_id])) {
            $this->success("查询成功", ['num' => 0, 'used' => 0]);
        }

        if (!empty($config['user_group'][$this->auth->group_id]) && $config['user_group'][$this->auth->group_id] == 'all') {
            $this->success("查询成功", ['num' => '100%', 'used' => 0]);
        }

        $used = db("mindmap_data")->where('user_id', $this->auth->id)->count();

        $this->success("查询成功", ['num' => $config['user_group'][$this->auth->group_id], 'used' => $used]);
    }
    /**
     * 主题列表
     */
    public function themelist()
    {
        $list = db("mindmap_theme")->where("status", '1')->order("weigh desc,id desc")->select();

        $array = [];

        if (!$list) {
            //当数据不存在时默认增加两条数据
            $list = [
                ['id' => 1, 'title' => '主题一', 'image' => '/assets/addons/mindmap/theme1.png', 'configdata' => '{"node":{"frist":{"type":"rest-rect","style":{"radius":4,"fill":"#2d8cf0"},"labelCfg":{"style":{"fontSize":18,"fill":"#ffffff","fontFamily":"Fantasy"}},"size":[120,50]},"second":{"type":"rest-rect","style":{"fill":"#ffffff","stroke":"#515a6e","lineWidth":0.5,"radius":4},"labelCfg":{"style":{"fontSize":16,"fill":"#515a6e"}},"size":[100,30]},"third":{"type":"third1","style":{"fillOpacity":0,"lineWidth":0},"labelCfg":{"style":{"fontSize":16,"fill":"#515a6e"}},"size":[100,50]}},"edge":{"type":"cubic-horizontal","style":{"radius":0,"stroke":"#515a6e","shadowColor":"","shadowBlur":0,"lineWidth":1,"strokeOpacity":1,"lineDash":[0]}},"layout":{"type":"compactBox","direction":"H","getHeight":72,"getWidth":36,"getVGap":10,"getHGap":100}}', 'status' => '1', 'weigh' => 2, 'createtime' => 1599206152, 'updatetime' => 1599206240],
                ['id' => 2, 'title' => '主题二', 'image' => '/assets/addons/mindmap/theme2.png', 'configdata' => '{"node":{"frist":{"type":"rest-rect","style":{"radius":4,"fill":"#000000"},"labelCfg":{"style":{"fontSize":18,"fill":"#ffffff","fontFamily":"Fantasy"}},"size":[120,80]},"second":{"type":"rest-rect","style":{"fill":"#515a6e","stroke":"#515a6e","lineWidth":0.5,"radius":4},"labelCfg":{"style":{"fontSize":16,"fill":"#ffffff"}},"size":[100,30]},"third":{"type":"rest-rect","style":{"fill":"#515a6e","stroke":"#515a6e","lineWidth":0.5,"radius":4},"labelCfg":{"style":{"fontSize":16,"fill":"#ffffff"}},"size":[100,30]}},"edge":{"type":"flow-line","style":{"radius":0,"stroke":"#515a6e","shadowColor":"","shadowBlur":0,"lineWidth":1,"strokeOpacity":1,"lineDash":[0]}},"layout":{"type":"compactBox","direction":"TB","getHeight":72,"getWidth":36,"getVGap":36,"getHGap":72}}', 'status' => '1', 'weigh' => 1, 'createtime' => 1599207172, 'updatetime' => 1599207172],
            ];

            db("mindmap_theme")->insertAll($list);
        }

        foreach ($list as $key => $value) {
            $array[$key]          = json_decode($value['configdata'], true);
            $array[$key]['id']    = $value['id'];
            $array[$key]['image'] = cdnurl($value['image'], true);
            $array[$key]['title'] = $value['title'];
        }

        if ($array) {
            $this->success('查询成功', $array);
        } else {
            $this->error('暂无主题信息');
        }
    }

    /**
     * [检查是否已经登陆]
     */
    public function checklogin()
    {
        $this->success('已登陆', $this->auth->getUserinfo());
    }

    /**
     * [会员登陆]
     */
    public function login()
    {
        if ($this->auth->id) {
            $this->success('已经登陆，不需重复登陆');
        }

        $account   = $this->request->post('account');
        $password  = $this->request->post('password');
        $keeplogin = (int) $this->request->post('keeplogin');
        $captcha   = $this->request->post('captcha');
        $rule      = [
            'account'  => 'require|length:3,50',
            'password' => 'require|length:6,30',
            'captcha'  => 'require|captcha',
        ];

        $msg = [
            'account.require'  => '账户不能为空',
            'account.length'   => '账户必须3-50个字符',
            'password.require' => '密码不能为空',
            'password.length'  => '密码必须6-30个字符',
            'captcha.require'  => '验证码不能为空',
            'captcha.captcha'  => '验证码错误',
        ];

        $data = [
            'account'  => $account,
            'password' => $password,
            'captcha'  => $captcha,
        ];

        $validate = new Validate($rule, $msg);
        $result   = $validate->check($data);

        if (!$result) {
            $this->error($validate->getError());
        }

        if ($this->auth->login($account, $password)) {
            $this->success('登陆成功', $this->auth->getUserinfo());
        } else {
            $this->error($this->auth->getError());
        }
    }

    /**
     * 注册会员
     */
    public function register()
    {
        if ($this->auth->id) {
            $this->success('已经登陆，不需重复登陆');
        }

        $username = $this->request->post('username');
        $password = $this->request->post('password');
        $email    = $this->request->post('email');
        $mobile   = $this->request->post('mobile', '');
        $captcha  = $this->request->post('captcha');
        $rule     = [
            'username' => 'require|length:3,30',
            'password' => 'require|length:6,30',
            'email'    => 'require|email',
            'mobile'   => 'regex:/^1\d{10}$/',
            'captcha'  => 'require|captcha',
        ];

        $msg = [
            'username.require' => '用户名不能为空',
            'username.length'  => 'Username must be 3 to 30 characters',
            'password.require' => 'Password can not be empty',
            'password.length'  => 'Password must be 6 to 30 characters',
            'email'            => 'Email is incorrect',
            'mobile'           => 'Mobile is incorrect',
            'captcha.require'  => '验证码不能为空',
            'captcha.captcha'  => '验证码错误',
        ];
        $data = [
            'username' => $username,
            'password' => $password,
            'email'    => $email,
            'mobile'   => $mobile,
            'captcha'  => $captcha,
        ];

        $validate = new Validate($rule, $msg);
        $result   = $validate->check($data);
        if (!$result) {
            $this->error($validate->getError());
        }
        if ($this->auth->register($username, $password, $email, $mobile)) {
            $this->success('注册成功', $this->auth->getUserinfo());
        } else {
            $this->error($this->auth->getError());
        }
    }

    /**
     * 注销登录
     */
    public function logout()
    {
        //注销本站
        $this->auth->logout();
        $this->success('退出成功');
    }

    /**
     * 重置密码
     */
    public function resetpwd()
    {
        $type        = $this->request->request("type");
        $mobile      = $this->request->request("mobile");
        $email       = $this->request->request("email");
        $newpassword = $this->request->request("newpassword");
        $captcha     = $this->request->request("captcha");
        if (!$newpassword || !$captcha) {
            $this->error(__('Invalid parameters'));
        }
        if ($type == 'mobile') {
            if (!Validate::regex($mobile, "^1\d{10}$")) {
                $this->error(__('Mobile is incorrect'));
            }
            $user = \app\common\model\User::getByMobile($mobile);
            if (!$user) {
                $this->error(__('User not found'));
            }
            $ret = Sms::check($mobile, $captcha, 'resetpwd');
            if (!$ret) {
                $this->error(__('Captcha is incorrect'));
            }
            Sms::flush($mobile, 'resetpwd');
        } else {
            if (!Validate::is($email, "email")) {
                $this->error(__('Email is incorrect'));
            }
            $user = \app\common\model\User::getByEmail($email);
            if (!$user) {
                $this->error(__('User not found'));
            }
            $ret = Ems::check($email, $captcha, 'resetpwd');
            if (!$ret) {
                $this->error(__('Captcha is incorrect'));
            }
            Ems::flush($email, 'resetpwd');
        }
        //模拟一次登录
        $this->auth->direct($user->id);
        $ret = $this->auth->changepwd($newpassword, '', true);
        if ($ret) {
            $this->success(__('Reset password successful'));
        } else {
            $this->error($this->auth->getError());
        }
    }

    /**
     * 查询当前用户的所有数据
     */
    public function getalldata()
    {
        $page = (int) $this->request->post('page', 1);
        $key  = $this->request->post('key');

        if ($key) {
            $where['title'] = array('like', "%$key%");
        }

        $where['user_id'] = $this->auth->id;
        $where['status']  = '1';

        $list = db("mindmap_data")->where($where)->page($page, '18')->order('weigh desc,id desc')->select();

        $total = db("mindmap_data")->where($where)->count();

        if ($list) {
            foreach ($list as $key => $value) {
                if ($value['image']) {
                    $list[$key]['image'] = cdnurl($value['image'], true);
                }
            }
            $this->success('查询成功', ['list' => $list, 'total' => $total]);
        } else {
            $this->error("暂无更多数据", $total);
        }
    }

    /**
     * 新增数据接口
     */
    public function create_file()
    {
        $title = $this->request->post('title');

        if (empty($title)) {
            $this->error("标题不能为空");
        }

        $config = get_addon_config('mindmap');

        if (empty($config['user_group'][$this->auth->group_id])) {
            $this->error("该会员等级没有权限操作");
        }

        if (!empty($config['user_group'][$this->auth->group_id]) && $config['user_group'][$this->auth->group_id] == 'all') {
            $this->add($title);
        }

        $num = db("mindmap_data")->where('user_id', $this->auth->id)->count();

        if ($config['user_group'][$this->auth->group_id] <= $num) {
            $this->error("文件已达上限");
        }

        $this->add($title);
    }

    /**
     * 操作新增数据
     */
    protected function add($title = '')
    {
        $data['title']      = $title;
        $data['user_id']    = $this->auth->id;
        $data['status']     = '1';
        $data['image']      = '';
        $data['data']       = '';
        $data['weigh']      = (db("mindmap_data")->where('user_id', $this->auth->id)->count() + 1);
        $data['createtime'] = time();
        $data['updatetime'] = time();

        $result = db("mindmap_data")->insert($data);

        if ($result) {
            $this->success("创建成功");
        } else {
            $this->error("创建失败，请重试");
        }
    }

    /**
     * 修改数据
     */
    public function edit_file()
    {
        $id   = (int) $this->request->post('id');
        $type = (int) $this->request->post('type', 1);

        $row = db("mindmap_data")->where(['id' => $id, 'user_id' => $this->auth->id])->find();

        if (!$row) {
            $this->error("文件不存在");
        }

        if ($type == 1) {
            //仅修改标题
            $title = $this->request->post('title');

            if (empty($title)) {
                $this->error("标题不能为空");
            }

            $result = db('mindmap_data')->where('id', $row['id'])->update(['title' => $title, 'updatetime' => time()]);
        } else {
            //修改数据
            $data = $this->request->post('data');
            $data = htmlspecialchars_decode($data);
            $data = html_entity_decode($data);
            $data = json_decode($data, true);

            $result = db('mindmap_data')->where('id', $row['id'])->update(['data' => json_encode($data), 'updatetime' => time()]);
        }

        if ($result) {
            $this->success("保存成功");
        } else {
            $this->error("保存失败，请重试");
        }
    }

    /**
     * 删除数据
     */
    public function delete()
    {
        $id = (int) $this->request->post('id');

        $result = db("mindmap_data")->where(['id' => $id, 'user_id' => $this->auth->id])->delete();

        if ($result) {
            $this->success("删除成功");
        } else {
            $this->error("删除失败，请重试");
        }
    }

    /**
     * 查询文件
     */
    public function get()
    {
        $id = (int) $this->request->post('id');

        $result = db("mindmap_data")->where(['id' => $id, 'user_id' => $this->auth->id])->find();

        if ($result) {

            $result['data'] = json_decode($result['data'], 1);

            $this->success("查询成功", $result);

        } else {
            $this->error("查询失败，请重试");
        }
    }

    /**
     * 下载文件
     */
    public function download()
    {
        $id = (int) $this->request->get('id');

        $row = db("mindmap_data")->where(['id' => $id, 'user_id' => $this->auth->id])->find();

        if (!$row) {
            $this->error("文件不存在");
        }

        $filename = uniqid() . '.json';

        header("Content-Type: application/octet-stream");

        if (preg_match("/MSIE/", $_SERVER['HTTP_USER_AGENT'])) {
            header('Content-Disposition:  attachment; filename="' . $filename . '"');
        } elseif (preg_match("/Firefox/", $_SERVER['HTTP_USER_AGENT'])) {
            header('Content-Disposition: attachment; filename*="utf8' . $filename . '"');
        } else {
            header('Content-Disposition: attachment; filename="' . $filename . '"');
        }

        echo $row['data'];
    }

    /**
     * 上传图片
     */
    public function savephoto()
    {
        $data = $this->request->post('data', '');

        $id = (int) $this->request->post('id');

        $row = db("mindmap_data")->where(['id' => $id, 'user_id' => $this->auth->id])->find();

        if (!$row) {
            $this->error("文件不存在");
        }

        if (!empty($data)) {

            $reg = '/data:image\/(\w+?);base64,(.+)$/si';
            preg_match($reg, $data, $match_result);

            $file_name = uniqid() . '.png';

            $wwwpath = DS . 'uploads' . DS . date('Ymd');
            $path    = ROOT_PATH . 'public' . $wwwpath;

            if (!is_dir($path)) {
                @mkdir($path, 0755, true);
            }

            $num = file_put_contents($path . DS . $file_name, base64_decode($match_result[2]));

            if (!empty($num)) {
                $result = db("mindmap_data")->where(['id' => $id, 'user_id' => $this->auth->id])->update(['image' => $wwwpath . DS . $file_name]);

                if ($result) {
                    $this->success("图片保存成功");
                } else {
                    $this->error("图片保存失败");
                }

            } else {
                $this->error("图片保存失败");
            }
        } else {
            $this->error("图片参数错误");
        }
    }

    /**
     * 上传文件
     * @ApiMethod (POST)
     * @param File $file 文件流
     */
    public function uploadfile()
    {

        $file = $this->request->file('file');
        if (empty($file)) {
            $this->error(__('No file upload or server upload limit exceeded'));
        }

        $id  = (int) $this->request->post('id');
        $row = db("mindmap_data")->where(['id' => $id, 'user_id' => $this->auth->id])->find();

        if (!$row) {
            $this->error("文件不存在");
        }

        //判断是否已经存在附件
        $sha1 = $file->hash();

        $upload = Config::get('upload');

        preg_match('/(\d+)(\w+)/', $upload['maxsize'], $matches);
        $type     = strtolower($matches[2]);
        $typeDict = ['b' => 0, 'k' => 1, 'kb' => 1, 'm' => 2, 'mb' => 2, 'gb' => 3, 'g' => 3];
        $size     = (int) $upload['maxsize'] * pow(1024, isset($typeDict[$type]) ? $typeDict[$type] : 0);
        $fileInfo = $file->getInfo();
        $suffix   = strtolower(pathinfo($fileInfo['name'], PATHINFO_EXTENSION));
        $suffix   = $suffix && preg_match("/^[a-zA-Z0-9]+$/", $suffix) ? $suffix : 'file';

        $mimetypeArr = explode(',', strtolower($upload['mimetype']));
        $typeArr     = explode('/', $fileInfo['type']);

        //禁止上传PHP和HTML文件
        if (in_array($fileInfo['type'], ['text/x-php', 'text/html']) || in_array($suffix, ['php', 'html', 'htm'])) {
            $this->error(__('Uploaded file format is limited'));
        }

        //验证文件后缀
        if ($fileInfo['type'] != 'application/json') {
            $this->error(__('Uploaded file format is limited'));
        }

        $replaceArr = [
            '{year}'     => date("Y"),
            '{mon}'      => date("m"),
            '{day}'      => date("d"),
            '{hour}'     => date("H"),
            '{min}'      => date("i"),
            '{sec}'      => date("s"),
            '{random}'   => Random::alnum(16),
            '{random32}' => Random::alnum(32),
            '{filename}' => $suffix ? substr($fileInfo['name'], 0, strripos($fileInfo['name'], '.')) : $fileInfo['name'],
            '{suffix}'   => $suffix,
            '{.suffix}'  => $suffix ? '.' . $suffix : '',
            '{filemd5}'  => md5_file($fileInfo['tmp_name']),
        ];
        $savekey = $upload['savekey'];
        $savekey = str_replace(array_keys($replaceArr), array_values($replaceArr), $savekey);

        $uploadDir = substr($savekey, 0, strripos($savekey, '/') + 1);
        $fileName  = substr($savekey, strripos($savekey, '/') + 1);
        //
        $splInfo = $file->validate(['size' => $size])->move(ROOT_PATH . '/public' . $uploadDir, $fileName);
        if ($splInfo) {
            $params = array(
                'admin_id'    => 0,
                'user_id'     => (int) $this->auth->id,
                'filesize'    => $fileInfo['size'],
                'imagewidth'  => 0,
                'imageheight' => 0,
                'imagetype'   => $suffix,
                'imageframes' => 0,
                'mimetype'    => $fileInfo['type'],
                'url'         => $uploadDir . $splInfo->getSaveName(),
                'uploadtime'  => time(),
                'storage'     => 'local',
                'sha1'        => $sha1,
            );
            $attachment = db("attachment");
            $attachment->insert(array_filter($params));
            \think\Hook::listen("upload_after", $attachment);

            $file_path = ROOT_PATH . 'public' . $uploadDir . $splInfo->getSaveName();
            if (file_exists($file_path)) {
                $content = file_get_contents($file_path);

                $result = db("mindmap_data")->where(['id' => $id, 'user_id' => $this->auth->id])->update(['data' => $content, 'updatetime' => time()]);

                if ($result) {
                    $this->success("导入成功");
                } else {
                    $this->error("导入失败");
                }
            }
        } else {
            // 上传失败获取错误信息
            $this->error($file->getError());
        }
    }
}
